package com.zzyl.nursing.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.BindFamilyDto;
import com.zzyl.nursing.dto.DeviceDataQueryDTO;
import com.zzyl.nursing.dto.DevicePropertyStatusDto;
import com.zzyl.nursing.dto.LoginUserDto;
import com.zzyl.nursing.mapper.FamilyMemberMapper;
import com.zzyl.nursing.service.*;
import com.zzyl.nursing.vo.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 老人家属Service业务层处理
 *
 * @author mr.wu
 * @date 2025-05-23
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService {
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private IElderService elderService;
    @Autowired
    private IElderMemberService elderMemberService;
    @Autowired
    private ICheckInService checkInService;
    @Autowired
    private IRoomService roomService;
    @Autowired
    private IAlertRuleService alertRuleService;


    /**
     * 查询老人家属
     *
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id) {
        return getById(id);
    }

    /**
     * 查询老人家属列表
     *
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember) {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 新增老人家属
     *
     * @param familyMember 老人家属
     * @return 结果
     */

    /**
     * 修改老人家属
     *
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember) {
        return updateById(familyMember) ? 1 : 0;
    }

    /**
     * 批量删除老人家属
     *
     * @param id 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long id) {
        return removeByIds(Arrays.asList(id)) ? 1 : 0;
    }

    /**
     * 删除老人家属信息
     *
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    @Autowired
    private WechatService wechatService;

    /**
     * 用户昵称名前缀集合
     */
    private static List<String> NICK_NAME_PREFIX_LIST = Arrays.asList("钱途无量",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝");

    @Autowired
    private TokenService tokenService;

    /**
     * 小程序登录
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoginUserVo login(LoginUserDto dto) {
        //1. 调用微信小程序登录接口获取openId
        String openId = wechatService.getOpenId(dto.getCode());
        if (StringUtils.isBlank(openId)) {
            throw new BaseException("获取openId失败");
        }

        //2. 根据openId查询用户数据
        FamilyMember member = this.lambdaQuery().eq(FamilyMember::getOpenId, openId).one();

        //3. 如果用户不存在，则新增用户（自动注册）
        if (member == null) {
            Collections.shuffle(NICK_NAME_PREFIX_LIST);

            //随机生成昵称
            String nickName = NICK_NAME_PREFIX_LIST.get(0) + RandomStringUtils.randomNumeric(4);

            member = FamilyMember.builder().name(nickName).openId(openId).build();
            boolean result = this.save(member);
            if (!result) {
                throw new BaseException("新增用户失败");
            }
        }

        //4. 判断用户手机号如果不存在，则调用微信获取手机号接口得到手机号
        if (StringUtils.isBlank(member.getPhone())) {
            String phone = wechatService.getPhone(dto.getPhoneCode());
            if (StringUtils.isBlank(phone)) {
                throw new BaseException("获取手机号失败");
            }

            //5. 得到手机号后则完成用户表的更新
            boolean result = this.lambdaUpdate().eq(FamilyMember::getId, member.getId())
                    .set(FamilyMember::getPhone, phone).update();
            if (!result) {
                throw new BaseException("更新手机号失败");
            }
        }

        //6. 生成登录成功用户的令牌（Token）
        Map<String, Object> userMap = new HashMap<>();
        userMap.put("userId", member.getId());//设置用户
        userMap.put("name", member.getName());//用户昵称
        String token = tokenService.createToken(userMap);//生成令牌

        //7. 构建响应数据
        return LoginUserVo.builder().nickName(member.getName()).token(token).build();
    }

    /**
     * 新增老人家属(绑定家人)
     *
     * @param dto 老人家属
     */
    @Override
    public void add(BindFamilyDto dto) {
        String name = dto.getName();//老人姓名
        String idCard = dto.getIdCard();//老人身份证号
        String remark = dto.getRemark();//客户对老人的称呼
        //根据老人身份证号查询老人信息
        Elder elder = elderService.getOne(new LambdaQueryWrapper<Elder>()
                .eq(Elder::getIdCardNo, idCard)
        );
        //获取当前登录人的id
        Long userId = UserThreadLocal.getUserId();
        //根据id查询登录人的信息
        FamilyMember familyMember = getById(userId);
        //往老人家属表里面封装数据
        ElderMember elderMember = new ElderMember();
        elderMember.setElderId(elder.getId());
        elderMember.setMemberId(familyMember.getId());
        elderMember.setRemark(remark);
        elderMemberService.save(elderMember);
    }

    /**
     * 查询家人列表
     *
     * @return
     */
    @Override
    public List<MyVo> selectFamily() {
        //得到当前登录人的id
        Long userId = UserThreadLocal.getUserId();
        //查询当前id关联的老人
        List<MyVo> myVos = new ArrayList<>();
        elderMemberService.getBaseMapper().selectList(
                new LambdaQueryWrapper<ElderMember>()
                        .eq(ElderMember::getMemberId, userId)
        ).forEach(x -> {
            Long elderId = x.getElderId();//获取老人id
            Elder elder = elderService.getById(elderId);//获取老人细信息
            String remark = x.getRemark();//查询备注信息
            Long id = x.getId();//获取id

            MyVo myVo = new MyVo();
            myVo.setFamilyMemberId(userId);
            myVo.setId(id);
            myVo.setElderId(elderId);
            myVo.setElderName(elder.getName());
            myVos.add(myVo);
        });
        return myVos;
    }

    @Autowired
    private IBedService bedService;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private IDeviceDataService deviceDataService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 查询家人列表（分页查询）
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public List<UserListVo> listByPage(Integer pageNum, Integer pageSize) {
        //新建一个集合，用来封装数据，接收数据并返回
        List<UserListVo> userListVos = new ArrayList<>();
        //查询所有的老人家属
        LambdaQueryWrapper<ElderMember> eq = new LambdaQueryWrapper<ElderMember>()
                .eq(ElderMember::getMemberId, UserThreadLocal.getUserId());
        List<ElderMember> elderMembers = elderMemberService.list(eq);
        elderMembers.forEach(x -> {
            Long elderId = x.getElderId();//老人id
            Long memberId = x.getMemberId();//老人家属id
            String remark = x.getRemark();//备注
            //根据老人id查询老人信息
            Elder elder = elderService.getById(elderId);
            String name = elder.getName();
            String image = elder.getImage();
            String bedNumber = elder.getBedNumber();
            Long bedId = elder.getBedId();
            //根据床位id查询床的房型
            Bed bed = bedService.getById(bedId);
            Long roomId = bed.getRoomId();
            Room room = roomService.getById(roomId);
            String typeName = room.getTypeName();
            //根据老人的id，查询老人绑定的设备iotId   deviceName   productKey三样信息
            List<Device> devices = deviceService.list(new LambdaQueryWrapper<Device>().eq(Device::getBindingLocation, elderId));
            if (ObjUtil.isEmpty(devices)) {
                //这种情况表示老人设备为空
                userListVos.add(new UserListVo(memberId, remark, elderId, name, image, bedNumber, typeName, null, null, null));
            } else {
                devices.forEach(item -> {
                    String iotId = item.getIotId();
                    String deviceName = item.getDeviceName();
                    String productKey = item.getProductKey();
                    userListVos.add(new UserListVo(memberId, remark, elderId, name, image, bedNumber, typeName, iotId, deviceName, productKey));
                });
            }
        });
        return userListVos;
    }

    /**
     * 查询健康数据
     *
     * @param dto
     * @return
     */
    @Override
    public DevicePropertyVo QueryDevicePropertyStatus(DevicePropertyStatusDto dto) {
        String deviceName = dto.getDeviceName();
        String productKey = dto.getProductKey();
        //查询device获取iotId
        Device device = deviceService.getOne(new LambdaQueryWrapper<Device>()
                .eq(Device::getDeviceName, deviceName)
                .eq(Device::getProductKey, productKey)
        );
        String iotId = device.getIotId();
        List<DeviceData> list = deviceDataService.list(
                new LambdaQueryWrapper<DeviceData>()
                        .eq(DeviceData::getDeviceName, deviceName)
                        .eq(DeviceData::getProductKey, productKey)
        );
        DevicePropertyVo devicePropertyVo = new DevicePropertyVo();
        PropertyStatusInfoVo propertyStatusInfoVo = new PropertyStatusInfoVo();
        List<InfoVo> infoVos = new ArrayList<>();
        list.forEach(deviceData -> {
            String functionId = deviceData.getFunctionId();
            String dataValue = deviceData.getDataValue();
            LocalDateTime alarmTime = deviceData.getAlarmTime();
            long timestampMillis = alarmTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli();
            if ("HeartRate".equals(functionId)) {
                String dataType = "int";
                String unit = "次/分";
                String name = "心率";
                InfoVo infoVo1 = new InfoVo(dataType, functionId, name, String.valueOf(timestampMillis), unit, dataValue);
                infoVos.add(infoVo1);
            } else if ("BodyTemp".equals(functionId)) {
                String dataType = "float";
                String unit = "°C";
                String name = "温度";
                InfoVo infoVo1 = new InfoVo(dataType, functionId, name, String.valueOf(timestampMillis), unit, dataValue);
                infoVos.add(infoVo1);
            } else if ("BatteryPercentage".equals(functionId)) {
                String dataType = "double";
                String unit = "%";
                String name = "用电量";
                InfoVo infoVo1 = new InfoVo(dataType, functionId, name, String.valueOf(timestampMillis), unit, dataValue);
                infoVos.add(infoVo1);
            } else if ("XueYang".equals(functionId)) {
                String dataType = "int";
                String unit = " ";
                String name = "血氧";
                InfoVo infoVo1 = new InfoVo(dataType, functionId, name, String.valueOf(timestampMillis), unit, dataValue);
                infoVos.add(infoVo1);
            }
        });
        propertyStatusInfoVo.setPropertyStatusInfo(infoVos);
        devicePropertyVo.setList(propertyStatusInfoVo);
        return devicePropertyVo;
    }

    /**
     * 按天统计查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<DeviceDataItemVO> queryDeviceDataListByDay(DeviceDataQueryDTO dto) {
        //判断是否为空
        if (ObjUtil.isEmpty(dto)) {
            throw new BaseException("参数为空，查询失败");
        }
        //查询数据
        Long startTime = dto.getStartTime();
        Long endTime = dto.getEndTime();
        if (startTime > endTime) {
            throw new BaseException("开始时间不能晚于结束时间");
        }
        LocalDateTime startDateTime = Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDateTime = Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        List<DeviceDataItemVO> list = familyMemberMapper.queryDeviceDataListByDay(dto, startDateTime, endDateTime);
        //返回
        if (CollUtil.isEmpty(list)) {
            throw new BaseException("查询数据为空");
        }
        return list;
    }

    /**
     * 按周统计查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<DeviceDataItemVO> queryDeviceDataListByWeek(DeviceDataQueryDTO dto) {
        // 查询数据
        long startTime = dto.getStartTime();
        long endTime = dto.getEndTime();
        if (startTime > endTime) {
            throw new BaseException("开始时间不能晚于结束时间！");
        }
        LocalDateTime startDateTime = Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDateTime = Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()).toLocalDateTime();

        // 日期数据
        List<DeviceDataItemVO> list = familyMemberMapper.queryDeviceDataListByWeek(dto, startDateTime, endDateTime);

        // 返回数据
        if (CollUtil.isEmpty(list)) {
            throw new BaseException("按天统计查询指标数据失败，查询数据为空！");
        }
        return list;
    }
}
